﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Marvin.Tests.MLAlgorithmsTests.LinearRegression
{
    /// <summary>
    /// Tests that linear regression can predict a straight line
    /// The straight line is defined by: y = 2 * (x-4) + 10
    /// </summary>
    [TestClass]
    public class StraightLinePrediction
    {
        /// <summary>
        /// The x in one dimension
        /// </summary>
        private readonly double[] _xOneD = new [] {-5.0, -3.0, -1.0, 0.0 };

        /// <summary>
        /// The y
        /// </summary>
        private readonly double[] _yOneD = new[]  {-8.0, -4.0,  0.0, 2.0 };

        /// <summary>
        /// Creates the one dimensional training set.
        /// </summary>
        /// <returns>the one dimensional training set</returns>
        private TrainingSet<double> CreateOneDimensionalTrainingSet()
        {
            var trainingSet = new TrainingSet<double>(1, _xOneD.Length);
            for (int i = 0; i < trainingSet.NumberOfTrainingExamples; i++)
            {
                trainingSet.Add(new[] { _xOneD[i]}, _yOneD[i] );
            }

            return trainingSet; 
        }

        /// <summary>
        /// The linear regression algorithm
        /// </summary>
        private Prediction.LinearRegression.LinearRegression _linearRegression;

        /// <summary>
        /// Trains the regression algorithm with one dimensional training set.
        /// </summary>
        [TestInitialize]
        public void TrainRegressionAlgorithmWithOneDimensionalTrainingSet()
        {
            var trainingSet = CreateOneDimensionalTrainingSet();
            _linearRegression = new Prediction.LinearRegression.LinearRegression();
            _linearRegression.Train(trainingSet); 
        }

        /// <summary>
        /// dimensional prediction of a point on the line is correct
        /// </summary>
        [TestMethod]
        public void OneDimensionalPredictionOfAPointOnTheLineIsCorrect()
        {
            const double expected = 8.0;
            var predicted = _linearRegression.Predict( new[] {3.0} );

            Assert.AreEqual(expected,predicted, 0.001);
        }
        
    }
}
